
/**
 * 输入框模糊查询插件
 * @require jquery1.9.1.js
 * @author genhuatu@hengtiansoft.com
 * @time 2013年9月10号
 */


jQuery.namespace('HZBank.app');

 if(!HZBank.app.PowerTips) {

	 HZBank.app.PowerTips = function(param) {

	     this.config = {
			 containerWrap       : '.container',
			 container           : '.auto-container', // 外部容器
			 urlroot             : urlroot,
			 treeRequestUrl      : '/lucene/searchOrgTree',
			 treeRequestOperUrl  : '/lucene/searchOperTree',
			 isLimitAuth         : true,			  // 是否控制权限
			 isGetOper           : false,			  // 是否显示操作员
			 showFatherNode      : false,              // 是否单独显示上级机构
			 chooseParent		 : false,			  // 是否允许选择上级机构	
			 treeOtherParam      : {'rootShow': false}, // 机构，树形查询传递的额外参数  rootShow当请求的数据是orgLucene的时候，配置是否要显示顶级根节点'杭州银行'
			 targetId            : '#luceneId',       // 输入框目标元素
			 selectElem          : '.auto-tips',      // 下拉框tips元素提示容器
			 position            : 'bottom',		  // 显示位置，默认显示在下方 可配置top,bottom
			 positionX			 : 'left',			  // 显示位置，默认显示在下方 可配置left，right
			 treeId              : '#ztree',          // 树形容器
			 luceneForm  		 :'#luceneForm', 	  //form表单
			 timeSpace           : '100',            //时间间隔 单位为 毫秒(ms) 默认为0.1秒
			 selectContainer     : '.select-content', // 被选中的容器
			 hideId              : '#all-id',         // 存放input 隐藏所有ID
			 elemTitle           : '.elem-title',     // 隐藏域 存放当前被选中的标题
			 operOrg             : '.oper-org',		  // 隐藏域 在选择机构下操作员时，记录操作员所属机构
		     url                 : '/json/data.json', // url接口
		     areaParent          : '',			    // 用于边界判定的基准对象，默认为self
			 width               : '411',           // 默认情况下输入框 下拉框 树形菜单宽度是411px;
			 
			 maxWidth			 : 'none',			// 下拉列表框最大宽度，默认 不限制(none)
			 maxHeight           : '210',	        // 默认情况下输入框 下拉框 树形菜单最大高度是210px;
			 showValue           : true,            //点击选项后，输入框显示ID还是名称，默认显示名称
			 initIdArrs          : '' ,               //传入的ID初始化已选择项所，逗号间隔
			 clickCallBack       : '',				//单选模式下，点击选项后的回调函数	
			 searchCallBack      : '',				//自定义查询链接查询后回调函数
			 searchInit          : ''				//自定义模糊匹配前自定义初始化
		 };
		 this.cache = {
			ret          : [],
			currentIndex : -1,
			oldIndex     : -1,
			DIYModel     : false,
			disable		 : false,
			pLintHeight  : 30,
			keyVal       : undefined,
			flag         : false,
			globalTime   : 0,
			idArrs       : [],
			timeFlag     : false,
			oldArrs      : [],
			timeFunc     : null
		 };
	 };

	 HZBank.app.PowerTips.prototype = {

		/**
		 * 整个程序初始化的执行入口,将传入的自定义参数对象customConfig与内部默认的config对象进行合并
		 * @param {Object} customConfig
		 */
		 init: function(customConfig){
			this.config = $.extend(this.config, customConfig || {});
			var  _self = this, _cache = _self.cache, _config = _self.config;
			var $target = $(_config.targetId);
			
			//如果定，则设置为自定义模糊匹配模式
			if(typeof _config.searchCallBack === "function"){
				_cache.DIYModel = true;
				//如果是自定义模糊匹配模式,执行自定义初始化
				if(typeof _config.searchInit === 'function'){
					_config.searchInit();
				}
			}else{
				// 如果没有自定义模糊匹配模式,则执行默认初始化
				_self.powerTipInit();
			}	
			
			//特殊字符过滤
			$target.unbind('input propertychange').bind('input propertychange',function(){
				var targetVal = $(this).val().replace(/[^A-Za-z0-9\u4e00-\u9fa5]/g,"");
				$(this).val(targetVal);
			});
			
			// 键盘起来的时候
			$target.unbind('keyup').bind('keyup',function(e){
				// 如果当前输入框不可用，不触发事件
				if(_cache.disable){return true;}
				
				if(_cache.DIYModel){
					var targetParent = $(e.target).closest(_config.containerWrap),
						targetVal = _self._trim($(this).val());
					if(_cache.keyVal != targetVal && _self._countCharacters(targetVal) >= 4) {
						//发送请求获取匹配结果
						 _self._sendPost(targetVal,targetParent);
						 _cache.keyVal = targetVal;
					}
				}else{
					_self.powerTipKeyUpFunc(e);
				}
				 
			});
			
			/* 当用户鼠标右键粘贴时，发送匹配请求 */
			$target.unbind('paste').bind('paste',function(e){
				// 如果当前输入框不可用，不触发事件
				if(_cache.disable){return true;}
				setTimeout(function(){
					var targetParent = $target.closest(_config.containerWrap),
						targetVal = _self._trim($target.val());
					//发送请求获取匹配结果
					 _self._sendPost(targetVal,targetParent);
					// 记录上一次输入值
					 _cache.keyVal = targetVal;
				},1);
				// 发生粘贴事件，必然使用模糊匹配，需要隐藏树形选择
				!$(_config.treeId).hasClass('hidden') && $(_config.treeId).addClass('hidden');
			});			
			
			// 获取是否需要绑定事件			
			if ($target.is('[disabled]') || $target.is('[disabled="true"]') || $target.is('[readonly]')
					|| $target.is('[readonly="readonly"]')) {
				this.disable();
			}
		 },
		 /* 非自定义查询模式下的模糊匹配初始化 */
		 powerTipInit:function(){
			 var  _self = this, _cache = _self.cache, _config = _self.config;
			
			var targetParent = $(_config.targetId).closest(_config.containerWrap);
			//如果没找到，则停止执行，防报错
			if(targetParent.length != 1){return false;}
				
			//获取input框宽度，下拉框最大高度和最大宽度
			_config.width = parseInt(_config.width);
			//根据最大宽度是否设置，决定是否格式化
			if(_config.maxWidth !== 'none'){
				//格式化最大宽度为数字，去边框
				_config.maxWidth = parseInt(_config.maxWidth) - 2;
			}			
			
			// 初始化时候 渲染输入框,下拉框,树形菜单的宽度
			_config.maxHeight = parseInt(_config.maxHeight);
			$(_config.targetId,targetParent).css('width',_config.width+"px");
			/* 设置下拉框，和树形下拉框 宽度，2为边框宽度 */
			$(_config.selectElem,targetParent).css({'min-width':(_config.width-2)+"px",'max-width':_config.maxWidth});
			$(_config.treeId,targetParent).css({'min-width':(_config.width-2)+"px",'max-height':(_config.maxHeight-2)+"px"});
			$(_config.selectElem,targetParent).css('overflow-y',"auto");
			// 控制输入框最大输入长度为100字符
			var maxInputLength = $(_config.targetId).attr('maxlength');
			// 如果没设置最长字符限制，或者限制长度大于50，则限制长度最长50字符
			if(!(maxInputLength && maxInputLength <= 50)){
				$(_config.targetId).attr('maxlength',"50");
			}
			
			// 确立下拉框显示位置（上下）
			_self._setPosition(targetParent);
			//判断左右显示位置
			_self._setPositionX(targetParent);
			
			//初始隐藏显示匹配结果框
			!$(_config.selectElem,targetParent).hasClass("hidden") && $(_config.selectElem,targetParent).addClass("hidden");
			
			// 鼠标点击输入框时候
			$(_config.targetId).focus(function(e){
				// 如果当前输入框不可用，不触发事件
				if(_cache.disable){return true;}
				
				var target = e.target,
					targetParent = $(target).closest(_config.containerWrap),
					targetVal = _self._trim($(this).val());
					// 如果是操作员的话 才渲染树的结构
				var noInputVal = $(_config.selectElem,targetParent).find('p').length === 0;
				if(_config.url == 'orgLucene' && targetVal == '' && noInputVal) {
					$(_config.treeId,targetParent).data("exit","true");		//标记树已经加载，方便控制mouseup事件中判断是否显示
					_self._showSelect($(_config.treeId,targetParent));
					_self._query(targetVal,targetParent);					
				}
			});
			
			//按下tab键切换到其他选择框时，关闭当前下拉框
			$(_config.targetId).unbind('keydown').bind('keydown',function(e){
				// 如果当前输入框不可用，不触发事件
				if(_cache.disable){return true;}				
				var keyCode = e.keyCode;
				//按下tab 9，切换到其他input 关闭下拉框
				if(keyCode == 9){_self._close();}
				//如果按下退格键，清除已输入信息
				if(keyCode == 8){_cache.keyVal = undefined;}		
			});
			
			//点击非控件位置，关闭选项框
			$(document).unbind('mouseup.container').bind('mouseup.container',function(e){
				// 如果当前输入框不可用，不触发事件
				var $target = $(e.target);
				if ($target.is('[disabled]') || $target.is('[disabled="true"]') || $target.is('[readonly]')
						|| $target.is('[readonly="readonly"]')) {
					return true;
				}
				
				//如果点击控件外区域，关闭下拉框，和被选中框
				if($(e.target).closest('.container').length == 0)
				{
					_self._close();
				}else if(e.target.nodeName === "INPUT"){
					//如果点击控件内的input，关闭下拉框，和被选中框
					_self._close();
					//显示当前input的下拉框，和被选中框
					var targetParent = $(e.target).closest(_config.containerWrap),
						targetVal = _self._trim($(e.target).val()),
						noInputVal = $(_config.selectElem,targetParent).find('p').length === 0 ,	//判断是否存在搜索数据
						isExitTree = $(targetParent).children('ul.ztree').data("exit");				//判断是否存在树
					if(isExitTree && noInputVal){	
						_self._showSelect($(targetParent).children('ul.ztree'));
					}
					if(!noInputVal){_self._showSelect($(_config.selectElem,targetParent));}
				}
			});
						
			//如果需要初始化
			 if(_config.initIdArrs !== '' && typeof _config.initIdArrs == "string"){		
				_self._doPostAction(_config.initIdArrs,targetParent);		 
			 }
			// 阻止form表单默认enter键提交
			$(_config.luceneForm).keydown(function(e){
				var keyCode = e.keyCode;
				if(keyCode == 13) {
					return false;
				}
			});
		 },
	 	/* 原始模糊匹配事件按下键盘事件处理 */
	 	powerTipKeyUpFunc: function(e){
	 		var  _self = this, _cache = _self.cache, _config = _self.config;
	 		 
			var target = e.target,
				targetParent = $(target).closest(_config.containerWrap),
				targetVal = _self._trim($(target).val()),
				keyCode = e.keyCode;
			
			 // 获取常用元素
			 var $selectElem = $(_config.selectElem,targetParent),
			 	 $treeId = $(_config.treeId,targetParent),
			 	 $elemTitle = $(_config.elemTitle,targetParent);		//隐藏域
			
			/** 键码判断 目的是想这些键按下时候 不发post请求
			 * ctrl 17,alt 18,箭头向上 38, 箭头向下 40, 向左 37 向右 39,
			 * 上页 33, 下页 34,end 35 delete 46 backspace 8 回车键 13 insert:45
			 * shift 16
			 */
			if(keyCode == 17 || keyCode == 18 || keyCode == 38 || keyCode == 40 || keyCode == 37 ||
			   keyCode == 39 || keyCode == 33 || keyCode == 34 || keyCode == 35 || keyCode == 46 || keyCode == 36 ||
			   keyCode == 13 || keyCode == 16 || keyCode == 45 || keyCode == 44 || keyCode == 145 || keyCode == 19 || keyCode == 20){
						
			   _self._keyUpAndDown(targetVal,e,targetParent);
			}else {
				//清除隐藏域中的结果
				$elemTitle.attr({"value":""});
				$elemTitle.attr({"data-title":""});
				$elemTitle.val('');
				// keyup时候 重新获取输入框的值 如果值为空的话 那树形菜单显示出来 否则 反之
				if(_self._trim(targetVal) !== '') {
					!$treeId.hasClass('hidden') && $treeId.addClass('hidden');
					// 如果匹配结果列表存在，则显示
					if($selectElem.children('p').length !== 0){
						// 显示匹配结果选项框
						_self._showSelect($selectElem);
					}
				 }else {						
					if(_config.url == 'orgLucene') {
						var treeObj = $.fn.zTree.getZTreeObj(_config.treeId.replace(/#/,""));
						//如果树不存在，则发送请求
						if(!treeObj){_self._query(targetVal,targetParent);}
						_self._showSelect($treeId);
					}
					!$selectElem.hasClass('hidden') && $selectElem.addClass('hidden');
					// 如果按键输入后，输入框内容为空，清除所有，回到初始状态
					_self.reset();
					return;
				 }

				 if(_cache.keyVal != targetVal && _self._countCharacters(targetVal) >= 4) {
					//发送请求获取匹配结果
					 _self._sendPost(targetVal,targetParent);
					 _cache.keyVal = targetVal;
				 }else if(_self._countCharacters(targetVal) < 4){
					//搜索后清空上一次结果,并隐藏结果输入框
					 !$selectElem.hasClass('hidden') && $selectElem.addClass('hidden');
					$(_config.selectElem + " p",targetParent).remove();					
					//恢复默认高度样式,即重新刷新选项框大小高度
					_self._reflashPosition(targetParent);
				 }
			}
		 },		 
		 _query: function(targetVal,targetParent){
			 var  _self = this, _cache = _self.cache, _config = _self.config;
			 if(_self._trim(targetVal) === '' && _cache.flag === false) {
					_cache.flag = true;
					var setting = {
							async: {
								enable: true,
								url:_config.urlroot + _config.treeRequestUrl,
								contentType : 'application/json; charset=UTF-8',
								dataType : 'json',
								autoParam:['id'],
								otherParam: $.extend(_config.treeOtherParam,{"isLimitAuth" : _config.isLimitAuth, "showFatherNode" : _config.showFatherNode})
							},
							callback: {
								onClick: zTreeOnClick,
								beforeClick: zTreeShowOper
							}
						};
					
					var zTree = $.fn.zTree.init($(_config.treeId),setting);				
				}
			 	
			 	function zTreeShowOper(treeId, treeNode){
			 		var treeObj = $.fn.zTree.getZTreeObj(treeId);
			 		var isOper = (treeNode.iconSkin == 'oper');
			 		if(_config.isGetOper && !treeNode.isParent && !isOper){
			 			treeNode.isParent = true;
			 			treeObj.updateNode(treeNode);
			 			treeObj.setting.async.url = _config.urlroot + _config.treeRequestOperUrl;
			 			treeObj.setting.async.otherParam = $.extend(treeObj.setting.async.otherParam,{"cid" : treeNode.id});
			 			treeObj.reAsyncChildNodes(treeNode,"refresh");
			 			//恢复参数
			 			treeObj.setting.async.url = _config.urlroot + _config.treeRequestUrl;
			 			treeObj.setting.async.otherParam = $.extend(_config.treeOtherParam,{"isLimitAuth" : _config.isLimitAuth, "showFatherNode" : _config.showFatherNode});		 			
			 			return false;
			 		}
			 		return true;
			 	}
				function zTreeOnClick(event, treeId, treeNode){
					var treeObj = $.fn.zTree.getZTreeObj(treeId);
					var isOper = (treeNode.iconSkin == 'oper');		//记录点击项是否是操作员
					var treeName = treeNode.name,
						treeId = treeNode.id,
					    isParent = treeNode.isParent;
					if(!isParent) {		
						//如果是点击的操作员，记录操作员所属机构
					 	if(_config.isGetOper && isOper){
					 		//所在节点的父节点tId
							var treeParent = treeObj.getNodeByTId(treeObj.getNodeByParam('id',treeId).parentTId);
							 //设置选项值到隐藏域
							 $(_config.operOrg,targetParent).attr({"value":treeParent.id});
							 $(_config.operOrg,targetParent).val(treeParent.id);
							 $(_config.operOrg,targetParent).attr({"data-title":treeParent.name});
					 	}
					 	//将所选项信息放入隐藏域，并在输入框中显示ID或名称，同时隐藏选择框
						_self._setValue(targetParent,treeId,treeName);
						//关闭下拉框
						_self._close();
					}else{
						//如果点击的是分支机构
						if(_config.chooseParent){
							//将所选项信息放入隐藏域，并在输入框中显示ID或名称，同时隐藏选择框
							_self._setValue(targetParent,treeId,treeName);		
							_self._close();
						}
					}							
				}
		 },
		 /**
		  * 键盘上下键操作
		  */
		 _keyUpAndDown: function(targetVal,e,targetParent) {
			var _self = this, _cache = _self.cache,	_config = _self.config;

			// 如果请求成功后 返回了数据(根据元素的长度来判断) 执行以下操作
			if($(_config.selectElem + ' p',targetParent) && $(_config.selectElem + ' p',targetParent).length > 0) {
				var plen = $(_config.selectElem + ' p',targetParent).length,
					keyCode = e.keyCode;
				_cache.oldIndex = _cache.currentIndex;

				// 上移操作
				if(keyCode == 38) {
					$(_config.selectElem,targetParent).hasClass('hidden') && $(_config.selectElem,targetParent).removeClass('hidden');
					if(_cache.currentIndex == -1) {
						_cache.currentIndex = plen - 1;
					}else {
						_cache.currentIndex = _cache.currentIndex - 1;
						if(_cache.currentIndex < 0) {
							_cache.currentIndex = plen - 1;
						}
					}
					//切换选中的元素
					changeSelected();
				}else if(keyCode == 40) { //下移操作
					$(_config.selectElem,targetParent).hasClass('hidden') && $(_config.selectElem,targetParent).removeClass('hidden');
					if(_cache.currentIndex == plen - 1) {
						_cache.currentIndex = 0;
					}else {
						_cache.currentIndex++;
						if(_cache.currentIndex > plen - 1) {
							_cache.currentIndex = 0;
						}
					}
					//切换选中的元素
					changeSelected();
				}else if(keyCode == 13) { //回车操作
					var curVal = $(_config.selectElem + ' .hover',targetParent).attr('data-title'),
						curId = $(_config.selectElem + ' .hover',targetParent).attr('data-html');
					//如果输入完直接按回车键，没有选择输入框中,则返回
					if(curVal == undefined){return false;}
					//将所选项信息放入隐藏域，并在输入框中显示ID或名称，同时隐藏选择框
					_self._setValue(targetParent,curId,curVal);	
					_cache.currentIndex = -1;
					_cache.oldIndex = -1;
				}
			}
			
			if(e.keyCode == 46){ //delete操作
				if(_config.showValue){
					var curVal = $(_config.elemTitle,targetParent).attr("data-title");
				}else{
					var curVal = $(_config.elemTitle,targetParent).attr("value");
				}

				if(curVal !== targetVal || targetVal === ""){_self.reset(false);}
				!$(_config.selectElem,targetParent).hasClass('hidden') && $(_config.selectElem,targetParent).addClass('hidden'); 
			}
			
			//判断当前选中元素是否被显示，不在则移动滚动条
			function ifScrollToSelf(){
				var $el = $(_config.selectElem + ' .p-index'+_cache.currentIndex,targetParent),
					$selectElem = $(_config.selectElem,targetParent);
				var elsHeight = $selectElem.height(),
					elHeight = $el[0].scrollHeight,
					top = $el.offset().top - $selectElem.offset().top - 1;  // 上方距离为：元素上偏移 - 选择框上偏移 - 选择框上边框1px
				/* 如果上偏移距离加上本身高度大于选择框高度（即下移时是否全部露出）
				 * 或者上偏移距离小于0(即上移是是否全部露出)
				 * 如果没有全部露出，则移动滚动条到当前项
				 */
				if(top + elHeight > elsHeight || top < 0){
					// 设置滚动到当前元素 ，即上方滚动条卷去的大小为序号*每一条数据高度
					$selectElem[0].scrollTop = (_cache.currentIndex) * elHeight;
				}
				
			}
			
			//　按下上移↑或者下移↓键时，切换选中的元素
			function changeSelected(){
				if(_cache.currentIndex !== -1) {
					$(_config.selectElem + ' .p-index'+_cache.currentIndex,targetParent).hasClass('out') &&
					$(_config.selectElem + ' .p-index'+_cache.currentIndex,targetParent).removeClass('out');

					!$(_config.selectElem + ' .p-index'+_cache.currentIndex,targetParent).hasClass('hover') &&
					$(_config.selectElem + ' .p-index'+_cache.currentIndex,targetParent).addClass('hover').siblings().removeClass('hover');
					var curAttr = $(_config.selectElem + ' .p-index'+_cache.currentIndex,targetParent).attr('data-html'),
						curTitle = $(_config.selectElem + ' .p-index'+_cache.currentIndex,targetParent).attr('data-title');
					ifScrollToSelf();
				}

				if(_cache.oldIndex !== -1 && plen !== 1) {
					$(_config.selectElem + ' .p-index'+_cache.oldIndex,targetParent).addClass('out');
				}
			}
		 },
		 /**
		   * 获取值 发post请求
		   */
		 _doPostAction: function(changeVal,targetParent){
			 var  _self = this, _cache = _self.cache, _config = _self.config,
				 url = _config.url,
				 api;
			 var _data = JSON.stringify({customerNameSearch: changeVal});
			 
			 switch(url){
			 case 'assetId':			// 对公客户查询
			 		api = urlroot + '/asset/select';
			 		break;
			 	case 'custLucene':			// 对公客户查询
			 		api = urlroot + '/lucene/searchCust';
			 		break;
			 	case 'privateCustLucene': 	// 个人客户查询
			 		api = urlroot + '/lucene/searchPrivateCust';
			 		break;
			 	case 'allCustLucene':		// 对公和个人客户查询		 
			 		api = urlroot + '/lucene/searchAllCust';
			 		break;
			 	case 'operLucene': 		    // 操作员查询
			 		api = urlroot + '/lucene/searchOper';
			 		break;
			 	case 'investorSearch': 		    // 投资管理人查询
			 		api = urlroot + '/ctstm/investorInfo/match';
			 		break;
			 	case 'areaLucene': 		    // 网点查询路径
			 		api = urlroot + '/lucene/searchNodeArea';
			 		break;
			 	case 'prodInfoSearch': 		    // 托管产品查询
			 		api = urlroot + '/ctstm/prodInfo/match';
			 		break;
			 	case 'accountInnerMatch': 		    // 行内账号信息查询
			 		api = urlroot + '/ctstm/oppAcc/innerMatch';
			 		break;
			 	case 'orgLucene': 		    // 机构查询
			 		api = urlroot + '/lucene/searchOrg';
					_data = JSON.stringify({customerNameSearch: changeVal,isLimitAuth: _config.isLimitAuth, showFatherNode : _config.showFatherNode});
			 		break;
			 	case 'posiLucene': 		    // 应用岗位查询
			 		api = urlroot + '/lucene/searchPosi';
			 		break;		
			 	default:
			 		// 自定义查询链接
			 		api = url;
			 		break;
			 }
			 
		  try{
				$.ajax({
					type: 'post',
					url: api,
					contentType : 'application/json; charset=UTF-8',
					dataType : 'JSON',
					data: _data,
					success: function(data){		
						//搜索后清空上一次结果
						$(_config.selectElem + " p",targetParent).remove();
						// 初始化选择索引值
						_cache.currentIndex = -1;
						
						// 由于有三种不同的请求url 所以返回的数据会有三种不同的格式及参数
						// 所以根据传进来的参数来进行相应的判断
						if(data.successed && data.returnObject.length > 0) {
							var returnObj = data.returnObject,
								objLen = returnObj.length;
							_cache.ret = [];
							 switch(url){
							 	case 'custLucene':			// 对公客户查询
							 	case 'privateCustLucene': 	// 个人客户查询
							 	case 'allCustLucene':		// 对公和个人客户查询		 
							 		_self._dealReturnObject(returnObj, objLen,'customerNo','customerName',targetParent);
							 		break;
							 	case 'operLucene': 		    // 操作员查询
							 		_self._dealReturnObject(returnObj, objLen,'operNo','alias',targetParent);
							 		break;
							 	case 'investorSearch': 		    // 投资管理人查询
							 	case 'prodInfoSearch': 		    // 托管产品查询
							 	case 'accountInnerMatch': 		    // 行内账号信息查询
							 		_self._dealReturnObject(returnObj, objLen,'dataId','dataValue',targetParent);
							 		break;
							 	case 'orgLucene': 		    // 机构查询
							 		_self._dealReturnObject(returnObj, objLen,'nodeCode','nodeNameX',targetParent);
							 		break;
							 	case 'areaLucene': 		    // 网点查询
							 		_self._dealReturnObject(returnObj, objLen,'areaCode','areaName',targetParent);
							 		break;
							 	case 'posiLucene': 		    // 应用岗位查询
							 		_self._dealReturnObject(returnObj, objLen,'appPosCode','detailDesc',targetParent);
							 		break;	
							 	case 'asset': 		    // 应用岗位查询
							 		_self._dealReturnObject(returnObj, objLen,'assetId','roomNum',targetParent);
							 		break;	
							 	default:
							 		// 自定义查询链接,如果是自定义处理模式
							 		if(_cache.DIYModel){
							 			_config.searchCallBack(data);
							 		}else{
							 			//如果没有自定义处理模式，调用默认处理方式处理数据
							 			_self._dealReturnObject(returnObj, objLen,'dataId','dataValue',targetParent);
							 		}
							 		break;
							 }
						}
						
						//默认处理事件
						if(!_cache.DIYModel){
							//非初始化时，搜索结果为空也显示空选择框进行交互
							 if(_config.initIdArrs === ''){
								 //显示结果框
								 _self._showSelect($(_config.selectElem,targetParent));
								 //根据当前内容刷新高度
								 _self._reflashPosition(targetParent);
							 }else{
								//如果需要初始化
								 _self._initData(targetParent);
							 }		 
						}else{
							//自定义处理中，如果没有查询到数据
							if(data.returnObject.length == 0){
								data.returnObject = "没有查询到数据";
								_config.searchCallBack(data);
							}
						}						
					},
					error  : function (XMLHttpRequest, textStatus, errorThrown) {
						//默认处理事件
						if(!_cache.DIYModel){
							//出错后停止初始化
							_config.initIdArrs = "";
							//清空存在的结果，并刷新高度，防止数据遗留
							$(_config.selectElem + " p",targetParent).remove();	
							// 还原选择索引值
							_cache.currentIndex = -1;
							_self._reflashPosition(targetParent);  //恢复默认高度样式,即重新刷新选项框大小高度
						}						
					}
				 });
			 }catch(e){
				alert('请求出错：' + e.message);
			 } 
		 },
		 /**
		  * 遍历所有数据，并格式化后进行html渲染和时间绑定
		  * @param  returnObj 返回的数据
		  * 		objLen  返回数据条数
		  * 		dataID  返回数据中ＩＤ字段名称
		  * 		dataName　返回数据中　数据值字段名
		  * 		targetParent 父元素
		  **/
		 _dealReturnObject: function(returnObj,objLen,dataID,dataName,targetParent){
			var _self = this, _cache = _self.cache,
			    curNo, curName, curNoNum;
			_cache.ret = [];
			for(var k = 0, klen = objLen; k < klen; k+=1) {
				curNo = returnObj[k][dataID];
				curName = returnObj[k][dataName];
				curNoNum = curNo + '-';
				_cache.ret.push(curNoNum.concat(curName));
			}
			_self._renderHTML(_cache.ret,targetParent);
			_self._executeClick(targetParent);
		 },
		 /**
		  * 对选项框中每一项绑定事件，点击后，将值设置到隐藏域，并添加输入移上效果
		  */
		 _executeClick: function(targetParent) {
			 var _self = this, _config = _self.config, _cache = _self.cache;
			 
			 // 获取常用元素
			 var $targetId = $(_config.targetId,targetParent),
			 	 $selectElem = $(_config.selectElem,targetParent);

			 $(_config.selectElem + ' p',targetParent).unbind('click').bind('click',function(e){		 
				 var dataAttr = $(this,targetParent).attr('data-html'),
				 dataTitle = $(this,targetParent).attr('data-title');
					  
				 //将所选项信息放入隐藏域，并在输入框中显示ID或名称，同时隐藏选择框，并执行点击回调事件
				 _self._setValue(targetParent,dataAttr,dataTitle);	
			 });
 
			 // 鼠标移上效果
			 $(_config.selectElem + ' p',targetParent).hover(function(e){
				 $(this).hasClass('out') && $(this).removeClass('out');
				 !$(this).hasClass('hover') && $(this).addClass('hover').siblings().removeClass('hover');	
				 //获取第一个className
				 var index = $(this).attr('class');
				 //获取第一个class的结束为止
				 var length = index.indexOf(" ");
				 // indexid为p-index后面的数字
				 var indexId = index.substring(7,length);
				 // 记录当前选中行
				 _cache.currentIndex = parseInt(indexId);
			 },function(){
				$(this).hasClass('hover') && $(this).removeClass('hover');
			 }); 
		 },
		 /**
		  * 渲染多少条数据
		  */
		 _renderHTML: function(ret,targetParent) {
			var _self = this, _config = _self.config, _cache = _self.cache,
				html = '';
			 // 获取常用元素
			 var $targetId = $(_config.targetId,targetParent),
			 	 $selectElem = $(_config.selectElem,targetParent);

			for(var i = 0, ilen = ret.length; i < ilen; i+=1) {
				html += '<p class="p-index'+i+'" data-html = '+ret[i].split('-')[0]+' data-title='+ret[i].split('-')[1]+' title='+ret[i]+'>'+ret[i]+'</p>';
			}

			$selectElem.html(html);
			!$selectElem.hasClass('border') && $selectElem.addClass('border');
			//刷新显示
			_self._reflashPosition(targetParent);
			
			var id = ret[0].split('-')[0],
				value = ret[0].split('-')[1];
			//查找第一个逗号，截取名称，如果没找到，说明全部都属于名称
			value = _self._subIndexOfChar(value,",");
			 
			var inputValue =  $(_config.targetId,targetParent).val();
			//如果搜索结果仅有一条数据，且输入框中的值等于id或者value，则放入隐藏域
			if(ret.length === 1 && (inputValue === value || inputValue === id)){				
				 $(_config.elemTitle,targetParent).attr({"value":id});
				 $(_config.elemTitle,targetParent).val(id);
				 $(_config.elemTitle,targetParent).attr({"data-title":value});
			}
		 },
		 /*
		  * 根据传入值初始ID，初始化选择信息
		  */
		 _initData : function(targetParent){
			 var _self = this,_config = _self.config,_cache = _self.cache;

			//找到存在的那项 
			$(_config.selectElem + ' p',targetParent).each(function(){						
				//找到需要初始化的那项
				if($(this).data("html")==_config.initIdArrs) {
					//将所选项信息放入隐藏域，并在输入框中显示ID或名称，同时隐藏选择框
					_self._setValue(targetParent,$(this).attr('data-html'),$(this).attr('data-title'));							
					_self._close();	
					return false;		// 跳出循环
				}
			});		
			//设置初始化已完成
			_config.initIdArrs = "";
		 },
		 /*
		  * 根据自己高度，刷新选择框大小及位置
		  */
		 _reflashPosition:function(targetParent){
			 var _self = this,_cache = _self.cache,_config = _self.config;	
			 
			 // 获取常用元素
			 var $targetId = $(_config.targetId,targetParent),
			 	 $selectElem = $(_config.selectElem,targetParent);

			 //获取选项框和被选中框中项目数
			 var plen = $(_config.selectElem + ' p',targetParent).length;

			 //如果选项框中数据项太多，限定高度
			 if(plen*_cache.pLintHeight > _config.maxHeight){
				 //数据长度超过最多显示数据
				 !($selectElem.css('height') == _config.maxHeight+'px')  && $selectElem.css('height',_config.maxHeight+'px');
				 //显示在上方时配置位置,27为输入框高度加边框25+2px
				 _config.position === "top" && $selectElem.css("margin-top","-"+ (_config.maxHeight+26)+"px");
			 }else{
				 // 如果之前是最大高度，则改为高度自适应
				 ($selectElem.css('height') == _config.maxHeight+'px')  && $selectElem.css('height','auto');
				 _config.position === "top" && $selectElem.css("margin-top","-"+ ($selectElem.height()+26)+"px");
			 }
			 
			 // 滚动条滚动到顶部
			 $selectElem[0].scrollTop = 0;
		 },
		 /* 将所选项信息放入隐藏域，并在输入框中显示ID或名称，同时隐藏选择框  */
		 _setValue: function(targetParent,id,value,flag){
			 var _config = this.config;	
			 
			 // 获取常用元素
			 var $targetId = $(_config.targetId,targetParent),
			 	 $selectElem = $(_config.selectElem,targetParent),
			 	 $treeId = $(_config.treeId,targetParent),
			 	 $elemTitle = $(_config.elemTitle,targetParent);
			 
			//查找第一个逗号，截取名称，如果没找到，说明全部都属于名称
			value = this._subIndexOfChar(value,",");
			 
			 //标志位记录是否隐藏选择框
			 flag == undefined && (flag = true);
			 
			 if(_config.showValue){
				 $targetId.val(value);
			 }else{
				 $targetId.val(id);
			 }
			 //设置选项值到隐藏域
			 $elemTitle.attr({"value":id});
			 $elemTitle.val(id);
			 $elemTitle.attr({"data-title":value});
			 if(flag){
				 !$selectElem.hasClass('hidden') && $selectElem.addClass('hidden');
				 !$treeId.hasClass('hidden') &&  $treeId.addClass('hidden');
			 }
			 
			  //执行选择完毕后的回调函数
			  if(typeof _config.clickCallBack === 'function'){
				_config.clickCallBack(id,value);
			  }
		 },
		 /** 
		  * 确立下拉框显示位置，targetParent为最外层容器,again表示是否为第二次判断，防止循环判断 
		  * 
		  **/
		 _setPosition: function(targetParent){
				var  _self = this,_cache = _self.cache,_config = _self.config;
				
				/* 上下位置判断，如果用户有设置，优先设置的值，否则进行边界判断,默认显示在下方 */
				_config.position = _self._borderAreaCheck(_config.position);
				
				//配置下拉框上下位置，添加样式 方便动态显示数据时 配置下拉框位置
				if(_config.position === "top"){
					$(_config.selectElem,targetParent).addClass("auto-tips-position-t");
					$(_config.treeId,targetParent).addClass("ztree-position-t");
					// 如果在上方显示，树形列表定高为最大高度
					$(_config.treeId,targetParent).css({"height":_config.maxHeight+"px","margin-top":"-"+(_config.maxHeight+24)+"px"});
				}
		 },
		 /** 
		  * 确立下拉框左右延伸显示位置，targetParent为最外层容器,again表示是否为第二次判断，防止循环判断 
		  * 
		  **/
		 _setPositionX: function(targetParent){
				var  _self = this,_cache = _self.cache,_config = _self.config;
				var $select = $(_config.selectElem,targetParent),
					$tree = $(_config.treeId,targetParent);
				
				/* 左右位置判断，如果用户有设置，优先设置的值，否则进行边界判断,默认显示左对齐，向右延伸 */
				_config.positionX = _self._borderAreaCheck(_config.positionX);
				
				// 配置下拉框左右位置
				switch(_config.positionX){
					case "left":
						$select.hasClass('right') && $select.removeClass('right');
						!$select.hasClass('left') && $select.addClass('left');
						$tree.hasClass('right') && $tree.removeClass('right');
						!$tree.hasClass('left') && $tree.addClass('left');
						break;
					case "right" :
						$select.hasClass('left') && $select.removeClass('left');
						!$select.hasClass('right') && $select.addClass('right');
						$tree.hasClass('left') && $tree.removeClass('left');
						!$tree.hasClass('right') && $tree.addClass('right');
						break;
					default :
						break;
				}
		 },
		 /**
		  *  边界判断，根据position判断是否足够显示
		  *  @param position 当前应该显示位置
		  *  @param again 是否第二次判断，防止死循环
		  *  @return position 返回最后确定应该显示位置
		  **/
		 _borderAreaCheck: function(position,again){
			 var  _self = this,_cache = _self.cache,_config = _self.config;
			 var targetParent = $(_config.targetId).closest(_config.containerWrap),
			     $target = $(_config.targetId,targetParent),
			     $areaParent = $(_config.areaParent);
			 // 进行边界控制的父元素的偏移
			 if(_config.areaParent !== '' && $areaParent.length > 0 ){
				 var body_width = $areaParent.width();
				 var body_height = $areaParent.height();
			 }else{
				 var body_width = $(self).width();
				 var body_height = $(self).height();
			 }

			 // 获取当前输入框位置，因为下拉框基于输入框定位，所以根据输入框位置定位
			 var input_t = $target.offset().top ,
			 	 input_l = $target.offset().left,
			 	 input_w = $target.width();
			 
			 // 下拉框实际占用位置
			 var height = _config.maxHeight,
			 	 width =  _config.maxWidth;
			 //如果没设置最大宽度，获取下拉框当前宽度
			 if(width == "none"){
				 //为避免一会儿左边，一会右边，默认设置为408, 为公共中一个li的最小宽度406+2px
				 width = 408;
			 }
				 
			 switch(position){
			 	case 'top':
			 		if(input_t < height){	//如果上方不足够显示，判断下方是否足够显示,只判断一次
			 			if(!again){
			 				position = _self._borderAreaCheck('bottom','again');
			 			}else{
			 				position = 'bottom';
			 			}			 			
			 		}
			 		break;
			 	case 'bottom':
			 		if((input_t + height + 25) > body_height){	//如果下方不足够显示，判断上方是否足够显示,只判断一次
			 			if(!again){
			 				position = _self._borderAreaCheck('top','again');
			 			}else{
			 				position = 'top';
			 			}	
			 		}
			 		break;
			 	case 'left':	//显示左对齐，即向右边延伸
			 		if((width + input_l) > body_width ){	//如果右方不足够显示，判断左方是否足够显示,只判断一次
			 			if(!again){
			 				position = _self._borderAreaCheck('right','again');
			 			}else{
			 				position = 'right';
			 			}	
			 		}
			 		break;
			 	case 'right':	//显示右对齐，即向左边延伸
			 		if(input_l + input_w < width ){	//如果左方不足够显示，判断右方是否足够显示,只判断一次
			 			if(!again){
			 				position = _self._borderAreaCheck('left','again');
			 			}else{
			 				position = 'left';
			 			}	
			 		}
			 		break;
			 	default:break;
			 }		
			 return position;			 
		 },		 
		 _trim: function(str){
		    return str.replace(/^\s+/,'').replace(/\s+$/,'');
		 },
		 // 计算字符的长度 包括中文 数字 英文等等
		 _countCharacters: function(str) {
			 var totalCount = 0;
		     for (var i=0; i<str.length; i++) {
		        var c = str.charCodeAt(i);
		     if ((c >= 0x0001 && c <= 0x007e) || (0xff60<=c && c<=0xff9f)) {
		           totalCount++;
		        }else {
		            totalCount+=2;
		        }
		     }
		     return totalCount;
		 },
		/**
		 *	剪切以某个字符分割的前部分
		 *  @param {value} 要处理的字符串
		 *  @param {char} 字符串分隔符
		 *  @return {value} 返回转换好的新的字符串，即第一个char之前的value部分
		 *  
		 **/
		_subIndexOfChar: function(value,char){
			//查找第一个char符号，如果没找到，说明不需要剪切
			var len = value.indexOf(char);
			if(len == -1){
				len = value.length;
			}			 
			value = value.substr(0,len);	
			
			return value;
		},
		/**
		 * 关闭下拉框（隐藏）
		 */
		_close: function(){
			var _self = this,_cache = _self.cache,_config = _self.config;
			// 隐藏页面中所有树形下拉框
			$(_config.containerWrap).children('ul.ztree').each(function(){
				!$(this).hasClass('hidden') && $(this).addClass('hidden');
			}); 
			// 隐藏页面中所有结果匹配框
			$(_config.selectElem).each(function(){
				!$(this).hasClass('hidden') && $(this).addClass('hidden');
			});						
			
		},
		/**
		 * 显示下拉列表
		 **/
		_showSelect: function($elem){
			$elem.hasClass('hidden') && $elem.removeClass('hidden');
			!$elem.hasClass('bg') && $elem.addClass('bg');
			!$elem.hasClass('border') && $elem.addClass('border');
		},
		/***   设置禁用所有事件   ***/
		disable:function(){
			this.cache.disable = true;
		},
		/***  设置启用用所有事件 ***/
		enable:function(){
			this.cache.disable = false;
		},
		/**
		 * 清空查询结果，回到初始化状态
		 * @param resetAll 表示是否清除全部，不设置默认清除全部
		 */
		reset:function(resetAll){
			var _self = this,_cache = _self.cache,_config = _self.config;
			var targetParent = $(_config.targetId).closest(_config.containerWrap);
			
			// 如果不设置，表示全部清除
			if(resetAll == undefined){resetAll = true;}
			if(resetAll){
				//清空输入框的值
				$(_config.targetId).val("");
			}
			
			//清空隐藏域的值
			$(_config.elemTitle,targetParent).attr({"value":""});
			$(_config.elemTitle,targetParent).val("");
			$(_config.elemTitle,targetParent).attr({"data-title":""});
			//清空上一次结果
			$(_config.selectElem + " p",targetParent).remove();
			//恢复默认高度样式,即重新刷新选项框大小高度
			_self._reflashPosition(targetParent);
			// 恢复默认
			_cache.keyVal = undefined;
		},
		/**
		 *	发动请求，增加延迟判断，防止快速发送请求消耗内存
		 *
		 *	@param targetVal 当前输入的值，需要进行模糊匹配的参数
		 *	@param targetParent 当前模糊匹配的输入框的最外层父元素
		 **/
		_sendPost:function(targetVal,targetParent){
			var _self = this,_cache = _self.cache,_config = _self.config;
			
			//设定新的计时器时，清除上一次
			clearTimeout(_cache.timeFunc);
			
			// 设定定时器,在timeSpace时间间隔后再发送请求，防止再timeSpace时间内 发送多次
			_cache.timeFunc = setTimeout(function(){
				_self._doPostAction(targetVal,targetParent);
//				_cache.keyVal = targetVal;
			},_config.timeSpace);
		},
		/**
		 * 对外公共函数： 验证是否输入域中的值与隐藏域中一致，如果不一致则提示输入有误
		 * @param str 为提示信息，默认为”必须选择自动匹配中的一项，否则输入无效！“
		 * @return 如果选择了提示项，即隐藏域中值与输入框中一致，则返回true，不一致，则清空输入并返回false
		 **/
		isChoose: function(str){
			var _self = this,_cache = _self.cache,_config = _self.config,
				$target = $(_config.targetId), $targetParent = $target.closest(_config.containerWrap), $elemTitle = $(_config.elemTitle,$targetParent);
			var textValue = $target.val(),
				hideId = $elemTitle.val(),		// 隐藏域中ID值
				hideValue = $elemTitle.attr("data-title");		// 隐藏域中valude值
			if(textValue == hideId || textValue == hideValue){
				return true;
			}else{
				str = str == undefined?'必须选择自动匹配中的一项，否则输入无效！':str;
				if($.isFunction(HZBank.showWarn)){
					HZBank.showWarn(str);
				}else{alert(str);}
				
				_self.reset(true);		
				return false;
			}
		},		
		/**
		 * 销毁事件 全局变量等等。
		 */
		destory: function(){
			var _self = this,_cache = _self.cache,_config = _self.config;
			$(_config.selectElem + ' p').unbind('click');
			$(_config.targetId).unbind('keyup');
			_self.url = '';
			_cache.ret = [];
			_cache.currentIndex = undefined;
			_cache.oldIndex = undefined;
		}
	 };
}